
#include "woptions/woptions.h"

class Options : public woptions::ProgramOptions
{
public:
	enum compilation_level_e
	{
		PREPROCESS,
		COMPILE,
		ASSEMBLE,
		LINK
	};
	
	Options() :
		outfile("a.out"),
		compile(LINK),
		standard("gnu89"),
		pedantic(false),
		debug_info(false),
		profile_info(false),
		optimisation_level(0)
	{
		arguments("infile",1,woptions::bind_argument_mem_fun(
			&source_files, &std::vector<std::string>::push_back));
		
		option("-c","","Compile, but do not link.",
			woptions::bind_option_value(compile,ASSEMBLE));
		option("-S","","Compile, but do not assemble.",
			woptions::bind_option_value(compile,COMPILE));
		option("-E","","Preprocess, but do not compile.",
			woptions::bind_option_value(compile,PREPROCESS));
		option("-g","","Generate debug information.",
			woptions::bind_option_value(debug_info,true));
		option("-p","","Generate profiler information.",
			woptions::bind_option_value(profile_info,true));
		option("-std","=standard","Specify the standard to which the code should conform.",
			woptions::bind_option_var(standard));
		option("-O","level","Set optimisation level.",
			woptions::bind_option_var(optimisation_level));
		option("-W","warning","Enable or disable warnings.",
			woptions::bind_option_mem_fun(&warnings, &std::vector<std::string>::push_back));
		option("-pedantic","","Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++.",
			woptions::bind_option_value(pedantic,true));
		option("-I","dir","Add the directory dir to the list of directories to be searched for header files.",
			woptions::bind_option_mem_fun(&include_dirs, &std::vector<std::string>::push_back));
		option("-L","dir","Add directory dir to the list of directories to be searched for -l.",
			woptions::bind_option_mem_fun(&lib_dirs, &std::vector<std::string>::push_back));
		option("-D","macro[=defn]","Predefine name as a macro.",
			woptions::bind_option_mem_fun(&define, &std::vector<std::string>::push_back));
		option("-U","macro","Cancel any previous definition of name, either built in or provided with a -D option.",
			woptions::bind_option_mem_fun(&undefine, &std::vector<std::string>::push_back));
		option("-f","option","Set gcc options.",
			woptions::bind_option_mem_fun(&options, &std::vector<std::string>::push_back));
		option("-m","machine-option","Set machine options.",
			woptions::bind_option_mem_fun(&machine_options, &std::vector<std::string>::push_back));
		option("-o","outfile","Specify output file.",
			woptions::bind_option_var(outfile));
		
	}
	
	std::vector<std::string> source_files;
	std::string outfile;
	
	compilation_level_e compile;
	
	std::vector<std::string> define;
	std::vector<std::string> undefine;
	std::vector<std::string> include_dirs;
	std::vector<std::string> lib_dirs;
	std::vector<std::string> warnings;
	std::vector<std::string> options;
	std::vector<std::string> machine_options;
	
	std::string standard;
	bool pedantic;
	bool debug_info;
	bool profile_info;
	int optimisation_level;
};

int main(int argc, char *argv[])
{
	Options opts;
	try
	{
		opts.parse(argc,argv);
		return 0;
	}
	catch(const woptions::ArgumentException& e)
	{
		opts.usage(argv[0]);
		std::cerr << e.what() << std::endl;
		return 1;
	}
}
